# Each team member would need to set their directory path to variable "project_dir"
# we will make sure everything else is relative to "project_dir"
project_dir <- "/home/admin-12/Documents/IMARTICUS/Data-Riders/EDA"
setwd(project_dir)

# Setup Packages
load_packages <- function () {
  # Imports
  packages <- c("VIM", "dplyr", "plotly", "psych", "corrplot", "cluster", "factoextra", "psych", "tm", "wordcloud2")
  installed_packages <- packages %in% rownames(installed.packages())
  if (any(installed_packages == FALSE)) {
    install.packages(packages[!installed_packages])
  }
  # Packages loading with suppressed messages
  suppressMessages(invisible(lapply(packages, library, character.only = TRUE)))
}
load_packages()

# Get the Raw Data from the file
read_file <- function () {
  data <- read.csv("data/cereals_data.csv")
  return (data)
}

# Handle missing values
handle_missing_values <- function (input) {
  output <- input
  output <- kNN(output)
  return (output)
}

# Clearn the data to make it good for processing
# eg. delete unwanted rows, change data types etc
data_processing <- function (input) {
  output <- input
  output <- handle_missing_values(output)

  # Set company names
  output$mfr_names <- as.character(output$mfr)
  output$mfr_names[output$mfr_names=="A"] <- "American Home Food Products"
  output$mfr_names[output$mfr_names=="G"] <- "General Mills"
  output$mfr_names[output$mfr_names=="K"] <- "Kelloggs"
  output$mfr_names[output$mfr_names=="N"] <- "Nabisco"
  output$mfr_names[output$mfr_names=="P"] <- "Post"
  output$mfr_names[output$mfr_names=="Q"] <- "Quaker Oats"
  output$mfr_names[output$mfr_names=="R"] <- "Ralston Purina"
  output$mfr_names_factor = as.factor(output$mfr_names)

  # Calorie Categories
  output <- within(output, {
    calories_category <- NA
    calories_category[calories>=50&calories<80] <- "L"
    calories_category[calories>=80&calories<110] <- "M"
    calories_category[calories>=110] <- "H"
  })

  # some data processing steps that would be required
  return (output)
}

# Get the Data Frame for the data
get_data <- function () {
  raw <- read_file()
  data <- data_processing(raw)
  return (data)
}

data <- get_data()
data_grp_mfr <- data %>% group_by(mfr_names_factor)

Part 1: Understanding Variables

Overall View
draw_density_plot <- function (value_set, xlab) {
  skewness <- round(skew(value_set), 2)
  mean <- round(mean(value_set), 2)
  median <- round(median(value_set), 2)
  title <- paste(xlab, "Density Chart   |  ", "Skewness:", skewness)
  plot(density(value_set), ylab = "Probabilty Density", xlab = xlab, main=title,)
  abline(v=mean, col="red")
  abline(v=median, col="blue")
}
Distribution of Calories (in the Products)
draw_density_plot(data$calories, "Calories")

Distribution of Ratings (for the Products)
draw_density_plot(data$rating, "Rating")

Part 2: Data Insights

Distribution of Rating vs Calorie Category
data %>% ggplot(aes(x = rating, fill = calories_category)) + geom_histogram() + scale_fill_brewer(palette = "Set1") +
        scale_x_continuous(name = "Ratings", expand = c(0,0)) +
        labs(fill = " Cal ", y ='Count', title = "Distribution of Rating vs Calorie Category", subtitle = "Higher the calories, Lower is the Rating") +
        theme_classic()
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Relationship of one variable with another
cor_result <- cor((data_grp_mfr %>% select_if(is.numeric))[-1])
corrplot(cor_result)

heatmap(cor_result)

good_bad_corr <- function (cor_result_filter) {
  #cor_result_filter <-
  cor_result_filter_names <- names(cor_result_filter)
  names(cor_result_filter) <- NULL
  cor_result_df <- data.frame(cor_result_filter_names, cor_result_filter) %>% arrange(cor_result_filter)
  names(cor_result_df) <- c("Parameters", "Corellation")
  ggplot(cor_result_df, aes(x=Parameters, y=Corellation)) + geom_bar(stat = "identity") +
          theme(axis.text.x=element_text(colour="black"), axis.text.y=element_text(colour="black"))
}
Influencers for Ratings
good_bad_corr(cor_result["rating",])

Influencers for Calories
good_bad_corr(cor_result["calories",])

Whats you get in one Serving
data %>% ggplot(aes(x = cups, fill = mfr_names)) +
        geom_histogram() +
        scale_x_continuous(name = "# of Cups", expand = c(0,0)) +
        labs(fill = "Manufacturer", title = "Distribution of Cups per Serving",
             subtitle = "different cups for servings", y="# of Products") +
        theme_classic() + scale_fill_brewer(palette="Dark2")
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

data %>% ggplot(aes(x = weight, fill = mfr_names)) + geom_histogram() +
    scale_x_continuous(name = "Weight (in ounces)", expand = c(0,0)) +
    labs(fill = "Manufacturer", title = "Distribution of Weight per Serving", subtitle = "Weight per serving") +
    theme_classic() + scale_fill_brewer(palette="Dark2")
`stat_bin()` using `bins = 30`. Pick better value with `binwidth`.

Best in the Market
d <- data %>% arrange(rating) %>% head(4) %>% select(name, rating)
ggplot(data=d, aes(x=name, y=rating)) + geom_bar(stat = "identity") +
        labs(y="Ratings") + scale_fill_brewer(palette="Dark2") +
        theme(axis.text.x=element_text(colour="black"), axis.text.y=element_text(colour="black"))

Part 3: Analysis by company

data_grp_mfr %>% plot_ly(y= ~rating, x= ~mfr_names_factor, type = "box", color= ~mfr_names_factor) %>%
  layout(title="Company wise Rating Consistency", xaxis=list(title="Manufactures"), yaxis=list(title="Rating"))

Part 4: Overall Picture

Word Cloud (error in markdown)

#get_file_content <- function () {
  #txt <- readLines("data/health.txt")
  #txt <- paste(txt, collapse = " ")
  #txt <- tolower(txt)
  #txt <- gsub("[^a-zA-Z]", " ", txt)
  #txt <- gsub("\\s+", " ", txt)
  #txt <- removeWords(txt, stopwords())
  #words <- strsplit(txt, " ")
  #word_freq <- table(words)
  #return (word_freq)
#}
#word_freq <- get_file_content()
#word_freq
#wordcloud2(word_freq, size=10)
Feature Based Grouping (Clusters)
cluster_data <- data %>% select(calories, rating, protein, fat) %>% scale
row.names(cluster_data) <- data[,1]
km.res <- kmeans(cluster_data, 5, nstart = 25)
fviz_cluster(km.res, data=cluster_data, palette = "jco", ggtheme = theme_minimal())

LS0tCnRpdGxlOiAiRGF0YSBSaWRlcnM6IEVEQSBNaW5pLVByb2plY3QiCm91dHB1dDoKICBodG1sX25vdGVib29rOgogICAgY29kZV9mb2xkaW5nOiBoaWRlCi0tLQoKPHN0eWxlIHR5cGU9InRleHQvY3NzIj4KCmg1IHsKICAgIGJhY2tncm91bmQ6IHJnYmEoMTA4LCAxMDgsIDEwOCwgMC4zNSk7CiAgICBib3JkZXItdG9wOiAxcHggc29saWQgIzg0ODQ4NDsKICAgIGJvcmRlci1ib3R0b206IDFweCBzb2xpZCAjODQ4NDg0OwogICAgbWFyZ2luLXRvcDogMHB4OwogICAgcGFkZGluZzogMTBweCAxMHB4OwogICAgZm9udC13ZWlnaHQ6IGJvbGQ7Cn0KaDU6aG92ZXIgewogIGJhY2tncm91bmQ6ICNmZmViM2I7Cn0KCmgyIHsKICBiYWNrZ3JvdW5kOiAjMjEyMTIxOwogIGNvbG9yOiB3aGl0ZTsKICBwYWRkaW5nOiA4cHggOHB4OwogIG1hcmdpbi10b3A6IDBweDsKICBtYXJnaW4tYm90dG9tOiAwcHg7Cn0KCi5jb250YWluZXItcGFydCB7CiAgYm9yZGVyOiAxcHggc29saWQgI2EyYTJhMjsKICBtYXJnaW4tYm90dG9tOiAzNXB4Owp9CgoubWFpbi1jb250YWluZXIgewogIG1heC13aWR0aDogMTMwMHB4OwogIG1hcmdpbi1sZWZ0OiBhdXRvOwogIG1hcmdpbi1yaWdodDogYXV0bzsKfQo8L3N0eWxlPgoKYGBge3J9CiMgRWFjaCB0ZWFtIG1lbWJlciB3b3VsZCBuZWVkIHRvIHNldCB0aGVpciBkaXJlY3RvcnkgcGF0aCB0byB2YXJpYWJsZSAicHJvamVjdF9kaXIiCiMgd2Ugd2lsbCBtYWtlIHN1cmUgZXZlcnl0aGluZyBlbHNlIGlzIHJlbGF0aXZlIHRvICJwcm9qZWN0X2RpciIKcHJvamVjdF9kaXIgPC0gIi9ob21lL2FkbWluLTEyL0RvY3VtZW50cy9JTUFSVElDVVMvRGF0YS1SaWRlcnMvRURBIgpzZXR3ZChwcm9qZWN0X2RpcikKCiMgU2V0dXAgUGFja2FnZXMKbG9hZF9wYWNrYWdlcyA8LSBmdW5jdGlvbiAoKSB7CiAgIyBJbXBvcnRzCiAgcGFja2FnZXMgPC0gYygiVklNIiwgImRwbHlyIiwgInBsb3RseSIsICJwc3ljaCIsICJjb3JycGxvdCIsICJjbHVzdGVyIiwgImZhY3RvZXh0cmEiLCAicHN5Y2giLCAidG0iLCAid29yZGNsb3VkMiIpCiAgaW5zdGFsbGVkX3BhY2thZ2VzIDwtIHBhY2thZ2VzICVpbiUgcm93bmFtZXMoaW5zdGFsbGVkLnBhY2thZ2VzKCkpCiAgaWYgKGFueShpbnN0YWxsZWRfcGFja2FnZXMgPT0gRkFMU0UpKSB7CiAgICBpbnN0YWxsLnBhY2thZ2VzKHBhY2thZ2VzWyFpbnN0YWxsZWRfcGFja2FnZXNdKQogIH0KICAjIFBhY2thZ2VzIGxvYWRpbmcgd2l0aCBzdXBwcmVzc2VkIG1lc3NhZ2VzCiAgc3VwcHJlc3NNZXNzYWdlcyhpbnZpc2libGUobGFwcGx5KHBhY2thZ2VzLCBsaWJyYXJ5LCBjaGFyYWN0ZXIub25seSA9IFRSVUUpKSkKfQpsb2FkX3BhY2thZ2VzKCkKCiMgR2V0IHRoZSBSYXcgRGF0YSBmcm9tIHRoZSBmaWxlCnJlYWRfZmlsZSA8LSBmdW5jdGlvbiAoKSB7CiAgZGF0YSA8LSByZWFkLmNzdigiZGF0YS9jZXJlYWxzX2RhdGEuY3N2IikKICByZXR1cm4gKGRhdGEpCn0KCiMgSGFuZGxlIG1pc3NpbmcgdmFsdWVzCmhhbmRsZV9taXNzaW5nX3ZhbHVlcyA8LSBmdW5jdGlvbiAoaW5wdXQpIHsKICBvdXRwdXQgPC0gaW5wdXQKICBvdXRwdXQgPC0ga05OKG91dHB1dCkKICByZXR1cm4gKG91dHB1dCkKfQoKIyBDbGVhcm4gdGhlIGRhdGEgdG8gbWFrZSBpdCBnb29kIGZvciBwcm9jZXNzaW5nCiMgZWcuIGRlbGV0ZSB1bndhbnRlZCByb3dzLCBjaGFuZ2UgZGF0YSB0eXBlcyBldGMKZGF0YV9wcm9jZXNzaW5nIDwtIGZ1bmN0aW9uIChpbnB1dCkgewogIG91dHB1dCA8LSBpbnB1dAogIG91dHB1dCA8LSBoYW5kbGVfbWlzc2luZ192YWx1ZXMob3V0cHV0KQoKICAjIFNldCBjb21wYW55IG5hbWVzCiAgb3V0cHV0JG1mcl9uYW1lcyA8LSBhcy5jaGFyYWN0ZXIob3V0cHV0JG1mcikKICBvdXRwdXQkbWZyX25hbWVzW291dHB1dCRtZnJfbmFtZXM9PSJBIl0gPC0gIkFtZXJpY2FuIEhvbWUgRm9vZCBQcm9kdWN0cyIKICBvdXRwdXQkbWZyX25hbWVzW291dHB1dCRtZnJfbmFtZXM9PSJHIl0gPC0gIkdlbmVyYWwgTWlsbHMiCiAgb3V0cHV0JG1mcl9uYW1lc1tvdXRwdXQkbWZyX25hbWVzPT0iSyJdIDwtICJLZWxsb2dncyIKICBvdXRwdXQkbWZyX25hbWVzW291dHB1dCRtZnJfbmFtZXM9PSJOIl0gPC0gIk5hYmlzY28iCiAgb3V0cHV0JG1mcl9uYW1lc1tvdXRwdXQkbWZyX25hbWVzPT0iUCJdIDwtICJQb3N0IgogIG91dHB1dCRtZnJfbmFtZXNbb3V0cHV0JG1mcl9uYW1lcz09IlEiXSA8LSAiUXVha2VyIE9hdHMiCiAgb3V0cHV0JG1mcl9uYW1lc1tvdXRwdXQkbWZyX25hbWVzPT0iUiJdIDwtICJSYWxzdG9uIFB1cmluYSIKICBvdXRwdXQkbWZyX25hbWVzX2ZhY3RvciA9IGFzLmZhY3RvcihvdXRwdXQkbWZyX25hbWVzKQoKICAjIENhbG9yaWUgQ2F0ZWdvcmllcwogIG91dHB1dCA8LSB3aXRoaW4ob3V0cHV0LCB7CiAgICBjYWxvcmllc19jYXRlZ29yeSA8LSBOQQogICAgY2Fsb3JpZXNfY2F0ZWdvcnlbY2Fsb3JpZXM+PTUwJmNhbG9yaWVzPDgwXSA8LSAiTCIKICAgIGNhbG9yaWVzX2NhdGVnb3J5W2NhbG9yaWVzPj04MCZjYWxvcmllczwxMTBdIDwtICJNIgogICAgY2Fsb3JpZXNfY2F0ZWdvcnlbY2Fsb3JpZXM+PTExMF0gPC0gIkgiCiAgfSkKCiAgIyBzb21lIGRhdGEgcHJvY2Vzc2luZyBzdGVwcyB0aGF0IHdvdWxkIGJlIHJlcXVpcmVkCiAgcmV0dXJuIChvdXRwdXQpCn0KCiMgR2V0IHRoZSBEYXRhIEZyYW1lIGZvciB0aGUgZGF0YQpnZXRfZGF0YSA8LSBmdW5jdGlvbiAoKSB7CiAgcmF3IDwtIHJlYWRfZmlsZSgpCiAgZGF0YSA8LSBkYXRhX3Byb2Nlc3NpbmcocmF3KQogIHJldHVybiAoZGF0YSkKfQoKZGF0YSA8LSBnZXRfZGF0YSgpCmRhdGFfZ3JwX21mciA8LSBkYXRhICU+JSBncm91cF9ieShtZnJfbmFtZXNfZmFjdG9yKQpgYGAKCjwhLS0gLS0tLS0tLS0tLSAtLS0tLS0tLS0tIC0tLS0tLS0tLS0gLS0tLS0tLS0tLSAtLT4KPGRpdiBjbGFzcz0iY29udGFpbmVyLXBhcnQiPgo8aDI+UGFydCAxOiBVbmRlcnN0YW5kaW5nIFZhcmlhYmxlczwvaDE+Cgo8aDU+T3ZlcmFsbCBWaWV3PC9oNT4KCmBgYHtyIGVjaG89RkFMU0UsIHdhcm5pbmc9RkFMU0V9CmRlc2NyaWJlKGRhdGEgJT4lIHNlbGVjdF9pZihpcy5udW1lcmljKSkKYGBgCgpgYGB7cn0KZHJhd19kZW5zaXR5X3Bsb3QgPC0gZnVuY3Rpb24gKHZhbHVlX3NldCwgeGxhYikgewogIHNrZXduZXNzIDwtIHJvdW5kKHNrZXcodmFsdWVfc2V0KSwgMikKICBtZWFuIDwtIHJvdW5kKG1lYW4odmFsdWVfc2V0KSwgMikKICBtZWRpYW4gPC0gcm91bmQobWVkaWFuKHZhbHVlX3NldCksIDIpCiAgdGl0bGUgPC0gcGFzdGUoeGxhYiwgIkRlbnNpdHkgQ2hhcnQgICB8ICAiLCAiU2tld25lc3M6Iiwgc2tld25lc3MpCiAgcGxvdChkZW5zaXR5KHZhbHVlX3NldCksIHlsYWIgPSAiUHJvYmFiaWx0eSBEZW5zaXR5IiwgeGxhYiA9IHhsYWIsIG1haW49dGl0bGUsKQogIGFibGluZSh2PW1lYW4sIGNvbD0icmVkIikKICBhYmxpbmUodj1tZWRpYW4sIGNvbD0iYmx1ZSIpCn0KYGBgCgo8aDU+RGlzdHJpYnV0aW9uIG9mIENhbG9yaWVzIChpbiB0aGUgUHJvZHVjdHMpPC9oNT4KYGBge3J9CmRyYXdfZGVuc2l0eV9wbG90KGRhdGEkY2Fsb3JpZXMsICJDYWxvcmllcyIpCmBgYAoKPGg1PkRpc3RyaWJ1dGlvbiBvZiBSYXRpbmdzIChmb3IgdGhlIFByb2R1Y3RzKTwvaDU+CmBgYHtyfQpkcmF3X2RlbnNpdHlfcGxvdChkYXRhJHJhdGluZywgIlJhdGluZyIpCmBgYAoKPC9kaXY+Cgo8IS0tIC0tLS0tLS0tLS0gLS0tLS0tLS0tLSAtLS0tLS0tLS0tIC0tLS0tLS0tLS0gLS0+CjxkaXYgY2xhc3M9ImNvbnRhaW5lci1wYXJ0Ij4KPGgyPlBhcnQgMjogRGF0YSBJbnNpZ2h0czwvaDE+Cgo8aDU+RGlzdHJpYnV0aW9uIG9mIFJhdGluZyB2cyBDYWxvcmllIENhdGVnb3J5PC9oNT4KYGBge3J9CmRhdGEgJT4lIGdncGxvdChhZXMoeCA9IHJhdGluZywgZmlsbCA9IGNhbG9yaWVzX2NhdGVnb3J5KSkgKyBnZW9tX2hpc3RvZ3JhbSgpICsgc2NhbGVfZmlsbF9icmV3ZXIocGFsZXR0ZSA9ICJTZXQxIikgKwogICAgICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIlJhdGluZ3MiLCBleHBhbmQgPSBjKDAsMCkpICsKICAgICAgICBsYWJzKGZpbGwgPSAiIENhbCAiLCB5ID0nQ291bnQnLCB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgUmF0aW5nIHZzIENhbG9yaWUgQ2F0ZWdvcnkiLCBzdWJ0aXRsZSA9ICJIaWdoZXIgdGhlIGNhbG9yaWVzLCBMb3dlciBpcyB0aGUgUmF0aW5nIikgKwogICAgICAgIHRoZW1lX2NsYXNzaWMoKQpgYGAKCjxoNT5SZWxhdGlvbnNoaXAgb2Ygb25lIHZhcmlhYmxlIHdpdGggYW5vdGhlcjwvaDU+CmBgYHtyfQpjb3JfcmVzdWx0IDwtIGNvcigoZGF0YV9ncnBfbWZyICU+JSBzZWxlY3RfaWYoaXMubnVtZXJpYykpWy0xXSkKY29ycnBsb3QoY29yX3Jlc3VsdCkKaGVhdG1hcChjb3JfcmVzdWx0KQpgYGAKCmBgYHtyfQpnb29kX2JhZF9jb3JyIDwtIGZ1bmN0aW9uIChjb3JfcmVzdWx0X2ZpbHRlcikgewogICNjb3JfcmVzdWx0X2ZpbHRlciA8LQogIGNvcl9yZXN1bHRfZmlsdGVyX25hbWVzIDwtIG5hbWVzKGNvcl9yZXN1bHRfZmlsdGVyKQogIG5hbWVzKGNvcl9yZXN1bHRfZmlsdGVyKSA8LSBOVUxMCiAgY29yX3Jlc3VsdF9kZiA8LSBkYXRhLmZyYW1lKGNvcl9yZXN1bHRfZmlsdGVyX25hbWVzLCBjb3JfcmVzdWx0X2ZpbHRlcikgJT4lIGFycmFuZ2UoY29yX3Jlc3VsdF9maWx0ZXIpCiAgbmFtZXMoY29yX3Jlc3VsdF9kZikgPC0gYygiUGFyYW1ldGVycyIsICJDb3JlbGxhdGlvbiIpCiAgZ2dwbG90KGNvcl9yZXN1bHRfZGYsIGFlcyh4PVBhcmFtZXRlcnMsIHk9Q29yZWxsYXRpb24pKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgICAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpLCBheGlzLnRleHQueT1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpKQp9CmBgYAoKPGg1PkluZmx1ZW5jZXJzIGZvciBSYXRpbmdzPC9oNT4KYGBge3J9Cmdvb2RfYmFkX2NvcnIoY29yX3Jlc3VsdFsicmF0aW5nIixdKQpgYGAKCjxoNT5JbmZsdWVuY2VycyBmb3IgQ2Fsb3JpZXM8L2g1PgpgYGB7cn0KZ29vZF9iYWRfY29ycihjb3JfcmVzdWx0WyJjYWxvcmllcyIsXSkKYGBgCgo8aDU+V2hhdHMgeW91IGdldCBpbiBvbmUgU2VydmluZzwvaDU+CmBgYHtyfQpkYXRhICU+JSBnZ3Bsb3QoYWVzKHggPSBjdXBzLCBmaWxsID0gbWZyX25hbWVzKSkgKwogICAgICAgIGdlb21faGlzdG9ncmFtKCkgKwogICAgICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIiMgb2YgQ3VwcyIsIGV4cGFuZCA9IGMoMCwwKSkgKwogICAgICAgIGxhYnMoZmlsbCA9ICJNYW51ZmFjdHVyZXIiLCB0aXRsZSA9ICJEaXN0cmlidXRpb24gb2YgQ3VwcyBwZXIgU2VydmluZyIsCiAgICAgICAgICAgICBzdWJ0aXRsZSA9ICJkaWZmZXJlbnQgY3VwcyBmb3Igc2VydmluZ3MiLCB5PSIjIG9mIFByb2R1Y3RzIikgKwogICAgICAgIHRoZW1lX2NsYXNzaWMoKSArIHNjYWxlX2ZpbGxfYnJld2VyKHBhbGV0dGU9IkRhcmsyIikKYGBgCgpgYGB7cn0KZGF0YSAlPiUgZ2dwbG90KGFlcyh4ID0gd2VpZ2h0LCBmaWxsID0gbWZyX25hbWVzKSkgKyBnZW9tX2hpc3RvZ3JhbSgpICsKICAgIHNjYWxlX3hfY29udGludW91cyhuYW1lID0gIldlaWdodCAoaW4gb3VuY2VzKSIsIGV4cGFuZCA9IGMoMCwwKSkgKwogICAgbGFicyhmaWxsID0gIk1hbnVmYWN0dXJlciIsIHRpdGxlID0gIkRpc3RyaWJ1dGlvbiBvZiBXZWlnaHQgcGVyIFNlcnZpbmciLCBzdWJ0aXRsZSA9ICJXZWlnaHQgcGVyIHNlcnZpbmciKSArCiAgICB0aGVtZV9jbGFzc2ljKCkgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpCmBgYAoKPGg1PkJlc3QgaW4gdGhlIE1hcmtldDwvaDU+CmBgYHtyfQpkIDwtIGRhdGEgJT4lIGFycmFuZ2UocmF0aW5nKSAlPiUgaGVhZCg0KSAlPiUgc2VsZWN0KG5hbWUsIHJhdGluZykKZ2dwbG90KGRhdGE9ZCwgYWVzKHg9bmFtZSwgeT1yYXRpbmcpKSArIGdlb21fYmFyKHN0YXQgPSAiaWRlbnRpdHkiKSArCiAgICAgICAgbGFicyh5PSJSYXRpbmdzIikgKyBzY2FsZV9maWxsX2JyZXdlcihwYWxldHRlPSJEYXJrMiIpICsKICAgICAgICB0aGVtZShheGlzLnRleHQueD1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpLCBheGlzLnRleHQueT1lbGVtZW50X3RleHQoY29sb3VyPSJibGFjayIpKQpgYGAKCjwvZGl2PgoKPCEtLSAtLS0tLS0tLS0tIC0tLS0tLS0tLS0gLS0tLS0tLS0tLSAtLS0tLS0tLS0tIC0tPgo8ZGl2IGNsYXNzPSJjb250YWluZXItcGFydCI+CjxoMj5QYXJ0IDM6IEFuYWx5c2lzIGJ5IGNvbXBhbnk8L2gxPgoKYGBge3Igb3V0LndpZHRoPSIxMDAlIn0KZGF0YV9ncnBfbWZyICU+JSBwbG90X2x5KHk9IH5yYXRpbmcsIHg9IH5tZnJfbmFtZXNfZmFjdG9yLCB0eXBlID0gImJveCIsIGNvbG9yPSB+bWZyX25hbWVzX2ZhY3RvcikgJT4lCiAgbGF5b3V0KHRpdGxlPSJDb21wYW55IHdpc2UgUmF0aW5nIENvbnNpc3RlbmN5IiwgeGF4aXM9bGlzdCh0aXRsZT0iTWFudWZhY3R1cmVzIiksIHlheGlzPWxpc3QodGl0bGU9IlJhdGluZyIpKQpgYGAKPC9kaXY+Cgo8ZGl2IGNsYXNzPSJjb250YWluZXItcGFydCI+CjxoMj5QYXJ0IDQ6IE92ZXJhbGwgUGljdHVyZTwvaDE+CgpXb3JkIENsb3VkIChlcnJvciBpbiBtYXJrZG93bikKYGBge3J9CiNnZXRfZmlsZV9jb250ZW50IDwtIGZ1bmN0aW9uICgpIHsKICAjdHh0IDwtIHJlYWRMaW5lcygiZGF0YS9oZWFsdGgudHh0IikKICAjdHh0IDwtIHBhc3RlKHR4dCwgY29sbGFwc2UgPSAiICIpCiAgI3R4dCA8LSB0b2xvd2VyKHR4dCkKICAjdHh0IDwtIGdzdWIoIlteYS16QS1aXSIsICIgIiwgdHh0KQogICN0eHQgPC0gZ3N1YigiXFxzKyIsICIgIiwgdHh0KQogICN0eHQgPC0gcmVtb3ZlV29yZHModHh0LCBzdG9wd29yZHMoKSkKICAjd29yZHMgPC0gc3Ryc3BsaXQodHh0LCAiICIpCiAgI3dvcmRfZnJlcSA8LSB0YWJsZSh3b3JkcykKICAjcmV0dXJuICh3b3JkX2ZyZXEpCiN9CiN3b3JkX2ZyZXEgPC0gZ2V0X2ZpbGVfY29udGVudCgpCiN3b3JkX2ZyZXEKI3dvcmRjbG91ZDIod29yZF9mcmVxLCBzaXplPTEwKQpgYGAKCjxoNT5GZWF0dXJlIEJhc2VkIEdyb3VwaW5nIChDbHVzdGVycyk8L2g1PgpgYGB7cn0KY2x1c3Rlcl9kYXRhIDwtIGRhdGEgJT4lIHNlbGVjdChjYWxvcmllcywgcmF0aW5nLCBwcm90ZWluLCBmYXQpICU+JSBzY2FsZQpyb3cubmFtZXMoY2x1c3Rlcl9kYXRhKSA8LSBkYXRhWywxXQprbS5yZXMgPC0ga21lYW5zKGNsdXN0ZXJfZGF0YSwgNSwgbnN0YXJ0ID0gMjUpCmZ2aXpfY2x1c3RlcihrbS5yZXMsIGRhdGE9Y2x1c3Rlcl9kYXRhLCBwYWxldHRlID0gImpjbyIsIGdndGhlbWUgPSB0aGVtZV9taW5pbWFsKCkpCmBgYAoKCg==